1# Migrating [Universal Modules][universal-modules] to TypeScript 2 3## Change Import 4 5To optimize our libraries for _dead code elimination_ we should migrate our exports to be imported as such: 6 7```diff 8 9- import { FileSystem } from 'expo-file-system'; 10 11+ import * as FileSystem from 'expo-file-system'; 12 13``` 14 15Ideally we would make the main entry-point of a module be a file named like the module like `build/FileSystem.js` 16 17**`package.json`** 18 19```diff 20- "main": "index.js", 21 22+ "main": "build/<MODULE NAME>.js", 23+ "types": "build/<MODULE NAME>.d.ts", 24``` 25 26To migrate from libraries using different imports, we should add a deprecation notice. 27 28> A lot of libraries are just import from Expo, in these cases we can just the deprecation. Ensure you change all imports across `packages/`, `apps/`, and `docs/`. 29 30**`src/index.ts`** 31 32```ts 33import * as FileSystem from './FileSystem'; 34export * from './FileSystem'; 35 36let wasImportWarningShown = false; 37// @ts-ignore: Temporarily define an export named "FileSystem" for legacy compatibility 38Object.defineProperty(exports, 'FileSystem', { 39 get() { 40 if (!wasImportWarningShown) { 41 console.warn( 42 `The syntax "import { FileSystem } from 'expo-file-system'" is deprecated. Use "import * as FileSystem from 'expo-file-system'" or import named exports instead. Support for the old syntax will be removed in SDK 34.` 43 ); 44 wasImportWarningShown = true; 45 } 46 return FileSystem; 47 }, 48}); 49``` 50 51Then eventually remove the index in favor of the named file. (`src/FileSystem.ts`) 52 53## Testing 54 55Migration should include the addition of a `src/__tests__` which can be run with `yarn test` in the root directory of the package. 56 571. If the package is using the old structure of `test/` for utilities, they should migrate to using `jest-expo`. 58 59**`src/__tests__/<MODULE NAME>-test.ts`** 60 61```diff 62- import { mockPlatformWeb } from '../../test/mocking'; 63 64+ import { mockPlatformWeb } from 'jest-expo'; 65``` 66 672. Add a jest object to the `package.json` 68 69**`package.json`** 70 71```js 72"jest": { 73 "preset": "expo-module-scripts" 74}, 75``` 76 773. Run `yarn test` to run the tests. 78 79### Add the tests to CI 80 81In the root `.circleci/config.yaml` add a step to the job named `expo_sdk`. This should be in alphabetic order with the other testing steps. 82 83**`.circleci/config.yaml`** 84 85```yaml 86- yarn: 87 command: test --maxWorkers 1 88 working_directory: ~/expo/packages/expo-sms 89``` 90 91## Move native `dependencies` to `peerDependencies` 92 93In order to prevent overlapping native code in `node_modules`, we should move any `dependencies` containing native code to `peerDependencies`. 94 95## Add module scripts 96 97**`package.json`** 98 99```js 100"scripts": { 101 "build": "expo-module build", 102 "clean": "expo-module clean", 103 "test": "expo-module test", 104 "prepare": "expo-module prepare", 105 "prepublishOnly": "expo-module prepublishOnly", 106 "expo-module": "expo-module" 107} 108``` 109 110## Generate a `tsconfig.json` file with `expo-module-scripts` 111 112To get the `tsconfig` that we use in all of our modules, run `expo-module prepare` or the yarn script `yarn prepare` (given the script is defined in a module's `package.json`) 113 114**`/tsconfig.json`** 115 116```json 117// @generated by expo-module-scripts 118{ 119 "extends": "expo-module-scripts/tsconfig.base", 120 "compilerOptions": { 121 "outDir": "./build" 122 }, 123 "include": ["./src"], 124 "exclude": ["**/__mocks__/*", "**/__tests__/*"] 125} 126``` 127 128## Various Other Changes 129 130- Remove `babel-preset-expo` 131- Remove `flow` 132- For reusing types across the web implementation's native layer and API layer, types should be moved to a named file with the `.types.ts` extension. There are cases (`expo-av` for example) where you should separate types into smaller files. 133 134[universal-modules]: https://github.com/expo/expo/blob/master/guides/Expo%20Universal%20Module%20Infrastructure.md 135